package com.yuyh.library.view.viewpager.indicator;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;

import com.yuyh.library.view.viewpager.indicator.slidebar.ScrollBar;


/**
 * 
 * @author试着飞
 * @date 2014年11月1日
 * @version 1.0 主要用于多个tab可以进行滑动
 */
public class ScrollIndicatorView extends HorizontalScrollView implements Indicator {
	private SFixedIndicatorView fixedIndicatorView;
	private boolean isPinnedTabView = false;
	private Paint defaultShadowPaint = null;
	private Drawable customShadowDrawable;
	private int shadowWidth;

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	public ScrollIndicatorView(Context context, AttributeSet attrs) {
		super(context, attrs);
		fixedIndicatorView = new SFixedIndicatorView(context);
		addView(fixedIndicatorView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
		setHorizontalScrollBarEnabled(false);
		setSplitAuto(true);

		defaultShadowPaint = new Paint();
		defaultShadowPaint.setAntiAlias(true);
		defaultShadowPaint.setColor(0x33AAAAAA);
		shadowWidth = dipToPix(3);
		defaultShadowPaint.setShadowLayer(shadowWidth, 0, 0, 0xFF000000);
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			setLayerType(View.LAYER_TYPE_SOFTWARE, null);
		}
	}

	public void setSplitAuto(boolean splitAuto) {
		setFillViewport(splitAuto);
		fixedIndicatorView.setSplitAuto(splitAuto);
	}

	public boolean isSplitAuto() {
		return fixedIndicatorView.isSplitAuto();
	}

	@Override
	public void setAdapter(IndicatorAdapter adapter) {
		if (getAdapter() != null) {
			getAdapter().unRegistDataSetObserver(dataSetObserver);
		}
		fixedIndicatorView.setAdapter(adapter);
		adapter.registDataSetObserver(dataSetObserver);
		dataSetObserver.onChange();
	}

	@Override
	public void setOnItemSelectListener(OnItemSelectedListener onItemSelectedListener) {
		fixedIndicatorView.setOnItemSelectListener(onItemSelectedListener);
	}

	@Override
	public IndicatorAdapter getAdapter() {
		return fixedIndicatorView.getAdapter();
	}

	public void setPinnedTabView(boolean isPinnedTabView) {
		this.isPinnedTabView = isPinnedTabView;
		if (isPinnedTabView) {
			if (fixedIndicatorView.getChildCount() > 0) {
				pinnedTabView = fixedIndicatorView.getChildAt(0);
			}
		}
		ViewCompat.postInvalidateOnAnimation(this);
	}

	public void setPinnedShadow(Drawable shadowDrawable, int shadowWidth) {
		this.customShadowDrawable = shadowDrawable;
		this.shadowWidth = shadowWidth;
		ViewCompat.postInvalidateOnAnimation(this);
	}

	public void setPinnedTabBg(Drawable pinnedTabBgDrawable) {
		this.pinnedTabBgDrawable = pinnedTabBgDrawable;
		ViewCompat.postInvalidateOnAnimation(this);
	}

	public void setPinnedTabBgColor(int color) {
		setPinnedTabBg(new ColorDrawable(color));
	}

	public void setPinnedTabBgId(int pinnedTabBgDrawableId) {
		setPinnedTabBg(ContextCompat.getDrawable(getContext(), pinnedTabBgDrawableId));
	}

	private Drawable pinnedTabBgDrawable;

	public void setPinnedShadow(int shadowDrawableId, int shadowWidth) {
		setPinnedShadow(ContextCompat.getDrawable(getContext(), shadowDrawableId), shadowWidth);
	}

	private DataSetObserver dataSetObserver = new DataSetObserver() {

		@Override
		public void onChange() {
			if (mTabSelector != null) {
				removeCallbacks(mTabSelector);
			}
			positionOffset = 0;
			setCurrentItem(fixedIndicatorView.getCurrentItem(), false);
			if (isPinnedTabView) {
				if (fixedIndicatorView.getChildCount() > 0) {
					pinnedTabView = fixedIndicatorView.getChildAt(0);
				}
			}
		}
	};

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();
		if (mTabSelector != null) {
			post(mTabSelector);
		}
	}

	@Override
	public void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		if (mTabSelector != null) {
			removeCallbacks(mTabSelector);
		}
	}

	private Runnable mTabSelector;
	private View pinnedTabView;
	private boolean mActionDownHappened;

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		if (fixedIndicatorView.getCount() > 0) {
			animateToTab(fixedIndicatorView.getCurrentItem());
		}
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (unScrollPosition != -1) {
			final View tabView = fixedIndicatorView.getChildAt(unScrollPosition);
			if (tabView != null) {
				final int scrollPos = tabView.getLeft() - (getMeasuredWidth() - tabView.getMeasuredWidth()) / 2;
				if (scrollPos >= 0) {
					smoothScrollTo(scrollPos, 0);
					unScrollPosition = -1;
				}
			}
		}
	}

	private void animateToTab(final int position) {
		if (position < 0 || position > fixedIndicatorView.getCount() - 1) {
			return;
		}
		final View tabView = fixedIndicatorView.getChildAt(position);
		if (mTabSelector != null) {
			removeCallbacks(mTabSelector);
		}
		mTabSelector = new Runnable() {
			public void run() {
				final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
				smoothScrollTo(scrollPos, 0);
				mTabSelector = null;
			}
		};
		post(mTabSelector);
	}

	@Override
	public void setCurrentItem(int item) {
		setCurrentItem(item, true);
	}

	@Override
	public void setCurrentItem(int item, boolean anim) {
		int count = fixedIndicatorView.getCount();
		if (count == 0) {
			return;
		}
		if (item < 0) {
			item = 0;
		} else if (item > count - 1) {
			item = count - 1;
		}
		unScrollPosition = -1;
		if (positionOffset < 0.02f || positionOffset > 0.98f) {
			if (anim) {
				animateToTab(item);
			} else {
				final View tabView = fixedIndicatorView.getChildAt(item);
				final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
				if (scrollPos >= 0) {
					scrollTo(scrollPos, 0);
				} else {
					unScrollPosition = item;
				}
			}
		}
		fixedIndicatorView.setCurrentItem(item, anim);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if (isPinnedTabView) {
			float x = ev.getX();
			float y = ev.getY();
			if (pinnedTabView != null && y >= pinnedTabView.getTop() && y <= pinnedTabView.getBottom() && x > pinnedTabView.getLeft()
					&& x < pinnedTabView.getRight()) {
				if (ev.getAction() == MotionEvent.ACTION_DOWN) {
					mActionDownHappened = true;
				} else if (ev.getAction() == MotionEvent.ACTION_UP) {
					if (mActionDownHappened) {
						pinnedTabView.performClick();
						invalidate(new Rect(0, 0, pinnedTabView.getMeasuredWidth(), pinnedTabView.getMeasuredHeight()));
						mActionDownHappened = false;
					}
				}
				return true;
			}
		}
		return super.dispatchTouchEvent(ev);
	}

	private int unScrollPosition = -1;

	@Override
	public int getCurrentItem() {
		return fixedIndicatorView.getCurrentItem();
	}

	@Override
	public OnItemSelectedListener getOnItemSelectListener() {
		return fixedIndicatorView.getOnItemSelectListener();
	}

	@Override
	public void setOnTransitionListener(OnTransitionListener onPageScrollListener) {
		fixedIndicatorView.setOnTransitionListener(onPageScrollListener);
	}

	@Override
	public OnTransitionListener getOnTransitionListener() {
		return fixedIndicatorView.getOnTransitionListener();
	}

	@Override
	public void setScrollBar(ScrollBar scrollBar) {
		fixedIndicatorView.setScrollBar(scrollBar);
	}

	private float positionOffset;

	@Override
	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
		this.positionOffset = positionOffset;
		final View tabView = fixedIndicatorView.getChildAt(position);
		if (tabView == null) {
			return;
		}
		final View tabView2 = fixedIndicatorView.getChildAt(position + 1);
		float offset = (tabView.getWidth() + (tabView2 == null ? tabView.getWidth() : tabView2.getWidth())) / 2 * positionOffset;
		final int scrollPos = (int) (tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2 + offset);
		scrollTo(scrollPos, 0);
		fixedIndicatorView.onPageScrolled(position, positionOffset, positionOffsetPixels);
	}

	@Override
	public void onPageScrollStateChanged(int state) {
		if (state == ViewPager.SCROLL_STATE_IDLE) {
			onPageScrolled(getCurrentItem(), 0, 0);
		}
	}

	@Override
	public int getPreSelectItem() {
		return fixedIndicatorView.getPreSelectItem();
	}

	@Override
	public View getItemView(int item) {
		return fixedIndicatorView.getItemView(item);
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
		if (isPinnedTabView) {
			int scrollX = getScrollX();
			if (pinnedTabView != null && scrollX > 0) {
				int saveCount = canvas.save();

				// 绘制固定在开始位置的pinnedTabView
				canvas.translate(scrollX + getPaddingLeft(), getPaddingTop());

				if (pinnedTabBgDrawable != null) {
					pinnedTabBgDrawable.setBounds(0, 0, pinnedTabView.getWidth(), pinnedTabView.getHeight());
					pinnedTabBgDrawable.draw(canvas);
				}

				ScrollBar scrollBar = fixedIndicatorView.getScrollBar();
				if (scrollBar != null && scrollBar.getGravity() == ScrollBar.Gravity.CENTENT_BACKGROUND) {
					drawScrollBar(canvas);
				}
				pinnedTabView.draw(canvas);
				if (scrollBar != null && scrollBar.getGravity() != ScrollBar.Gravity.CENTENT_BACKGROUND) {
					drawScrollBar(canvas);
				}

				int x = pinnedTabView.getWidth();
				// pinnedTabView的分割绘制阴影
				canvas.translate(x, 0);
				int shadowHeight = getHeight() - getPaddingTop() - getPaddingBottom();
				if (customShadowDrawable != null) {
					customShadowDrawable.setBounds(0, 0, shadowWidth, shadowHeight);
					customShadowDrawable.draw(canvas);
				} else {
					canvas.clipRect(0, 0, shadowWidth + dipToPix(1), shadowHeight);
					canvas.drawRect(0, 0, dipToPix(1), shadowHeight, defaultShadowPaint);
				}

				canvas.restoreToCount(saveCount);
			}
		}
	}

	private void drawScrollBar(Canvas canvas) {
		ScrollBar scrollBar = fixedIndicatorView.getScrollBar();
		// 如果scrollBar不为空，且刚好选中的是第一个的时候需要在这里重新绘制scrollBar，因为原先fixedIndicatorView回执的scrollBar被遮挡了
		if (scrollBar != null && fixedIndicatorView.getCurrentItem() == 0) {
			int drawScrollBarCount = canvas.save();

			int offsetY = 0;
			switch (scrollBar.getGravity()) {
			case CENTENT_BACKGROUND:
			case CENTENT:
				offsetY = (getHeight() - scrollBar.getHeight(getHeight())) / 2;
				break;
			case TOP:
			case TOP_FLOAT:
				offsetY = 0;
				break;
			case BOTTOM:
			case BOTTOM_FLOAT:
			default:
				offsetY = getHeight() - scrollBar.getHeight(getHeight());
				break;
			}
			int scrollBarWidth = scrollBar.getWidth(pinnedTabView.getWidth());
			int scrollBarHeight = scrollBar.getHeight(pinnedTabView.getHeight());
			scrollBar.getSlideView().measure(scrollBarWidth, scrollBarHeight);
			scrollBar.getSlideView().layout(0, 0, scrollBarWidth, scrollBarHeight);

			int offsetX = (pinnedTabView.getWidth() - scrollBarWidth) / 2;

			canvas.translate(offsetX, offsetY);
			canvas.clipRect(0, 0, scrollBarWidth, scrollBarHeight); // needed
			scrollBar.getSlideView().draw(canvas);

			canvas.restoreToCount(drawScrollBarCount);
		}
	}

	private static class SFixedIndicatorView extends FixedIndicatorView {

		private boolean isAutoSplit;

		public SFixedIndicatorView(Context context) {
			super(context);
		}

		public boolean isSplitAuto() {
			return isAutoSplit;
		}

		public void setSplitAuto(boolean isAutoSplit) {
			if (this.isAutoSplit != isAutoSplit) {
				this.isAutoSplit = isAutoSplit;
				if (!isAutoSplit) {
					setSplitMethod(SPLITMETHOD_WRAP);
				}
				requestLayout();
				invalidate();
			}
		}

		@Override
		protected void onMeasure(int widthSpec, int heightSpec) {
			if (isAutoSplit) {
				ScrollIndicatorView group = (ScrollIndicatorView) getParent();
				int layoutWidth = group.getMeasuredWidth();
				if (layoutWidth != 0) {
					int totalWidth = 0;
					int count = getChildCount();
					int maxCellWidth = 0;
					for (int i = 0; i < count; i++) {
						int width = measureChildWidth(getChildAt(i), widthSpec, heightSpec);
						maxCellWidth = maxCellWidth < width ? width : maxCellWidth;
						totalWidth += width;
					}
					if (totalWidth > layoutWidth) {
						group.setFillViewport(false);
						setSplitMethod(SPLITMETHOD_WRAP);
					} else if (maxCellWidth * count > layoutWidth) {
						group.setFillViewport(true);
						setSplitMethod(SPLITMETHOD_WEIGHT);
					} else {
						group.setFillViewport(true);
						setSplitMethod(SPLITMETHOD_EQUALS);
					}
				}
			}
			super.onMeasure(widthSpec, heightSpec);
		}

		private int measureChildWidth(View view, int widthSpec, int heightSpec) {
			LayoutParams p = (LayoutParams) view.getLayoutParams();
			int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), LayoutParams.WRAP_CONTENT);
			int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height);
			view.measure(childWidthSpec, childHeightSpec);
			return view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
		}

	}

	/**
	 * 根据dip值转化成px值
	 * 
	 * @param dip
	 * @return
	 */
	private int dipToPix(float dip) {
		int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
		return size;
	}

}
